package com.xu.minio.utils;

import com.xu.minio.model.MinioFile;
import com.xu.minio.prop.MinioProperties;
import io.minio.*;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * minio工具类
 *
 * @Author: 许乾伟
 * @Date: 2024/3/8 13:08
 */
@Component
public class MinioService {
    @Resource
    MinioProperties properties;
    @Resource
    MinioClient minioClient;

    /**
     * 创建一个桶
     * @param bucketName 桶名称
     * @return true 创建成功/false 创建失败
     * @throws Exception 抛出异常
     */
    public Boolean createBucket(String bucketName) throws Exception {
        if (minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            return Boolean.TRUE;
        }
        //创建桶
        minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        //桶授权
        String policy = "{\n" +
                "\t\"Version\": \"2012-10-17\",\n" +
                "\t\"Statement\": [{\n" +
                "\t\t\"Effect\": \"Allow\",\n" +
                "\t\t\"Principal\": {\n" +
                "\t\t\t\"AWS\": [\"*\"]\n" +
                "\t\t},\n" +
                "\t\t\"Action\": [\"s3:GetBucketLocation\", \"s3:ListBucket\", \"s3:ListBucketMultipartUploads\"],\n" +
                "\t\t\"Resource\": [\"arn:aws:s3:::"+bucketName+"\"]\n" +
                "\t}, {\n" +
                "\t\t\"Effect\": \"Allow\",\n" +
                "\t\t\"Principal\": {\n" +
                "\t\t\t\"AWS\": [\"*\"]\n" +
                "\t\t},\n" +
                "\t\t\"Action\": [\"s3:AbortMultipartUpload\", \"s3:DeleteObject\", \"s3:GetObject\", \"s3:ListMultipartUploadParts\", \"s3:PutObject\"],\n" +
                "\t\t\"Resource\": [\"arn:aws:s3:::"+bucketName+"/*\"]\n" +
                "\t}]\n" +
                "}";
        minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policy).build());
        return Boolean.TRUE;
    }
    /**
     * 保存MultipartFile文件到默认桶
     * @param file 文件
     * @return 保存到minio后的文件信息
     * @throws Exception 抛出异常
     */
    public MinioFile uploadMultipartFile(MultipartFile file) throws Exception {
        return uploadMultipartFile(file, properties.getBucketName());
    }

    /**
     * 保存MultipartFile文件到指定桶
     * @param file 文件
     * @param bucketName 桶名称
     * @return 保存到minio后的文件信息
     * @throws Exception 抛出异常
     */
    public MinioFile uploadMultipartFile(MultipartFile file,String bucketName) throws Exception {
        return uploadInputStream(file.getInputStream(), file.getSize(), file.getContentType(), file.getOriginalFilename(), bucketName);
    }

    /**
     * 保存文件流到默认桶
     * @param inputStream 文件流
     * @param fileSize 文件大小
     * @param fileType 文件类型
     * @param originalFilename 文件名
     * @return 保存到minio后的文件信息
     * @throws Exception 抛出异常
     */
    public MinioFile uploadInputStream(InputStream inputStream,Long fileSize,String fileType,String originalFilename) throws Exception {
        return uploadInputStream(inputStream,fileSize,fileType,originalFilename,properties.getBucketName());
    }

    /**
     * 保存文件流到指定桶
     * @param inputStream 文件流
     * @param fileSize 文件大小
     * @param fileType 文件类型
     * @param originalFilename 文件名
     * @param bucketName 桶名称
     * @return 保存到minio后的文件信息
     * @throws Exception 抛出异常
     */
    public MinioFile uploadInputStream(InputStream inputStream,Long fileSize,String fileType,String originalFilename,String bucketName) throws Exception {
        String fileDate = getDateFormat();
        String fileName = UUID.randomUUID().toString().replace("-", "") + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = String.format("%s/%s", fileDate, fileName);
        //创建桶
        createBucket(bucketName);

        //存储文件
        PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(objectName)
                .stream(inputStream, fileSize, -1)
                .contentType(fileType)
                .build();
        minioClient.putObject(objectArgs);
        String url = String.format("%s/%s/%s", properties.getEndpoint(), bucketName, objectName);
        MinioFile minioFile = new MinioFile();
        minioFile.setFileName(originalFilename);
        minioFile.setMinioFileName(objectName);
        minioFile.setFilePath(url);
        minioFile.setFileType(fileType);
        minioFile.setFileSize(fileSize);
        return minioFile;
    }
    /**
     * 删除默认桶的文件
     * @param minioFileName minio文件名称
     * @return true 删除成功/false 删除失败
     * @throws Exception 抛出异常
     */
    public Boolean removeFile(String minioFileName) throws Exception {
       removeFile(properties.getBucketName(),minioFileName);
        return Boolean.TRUE;
    }

    /**
     * 删除指定桶的文件
     * @param bucketName 桶名称
     * @param minioFileName minio文件名称
     * @return true 删除成功/false 删除失败
     * @throws Exception 抛出异常
     */
    public Boolean removeFile(String bucketName,String minioFileName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(minioFileName).build());
        return Boolean.TRUE;
    }

    /**
     * 获取文件basePath
     * @return
     */
    public String basePath(){
        return String.format("%s/%s", properties.getEndpoint(), properties.getBucketName());
    }

    /**
     * 返回当前日期格式字符串,yyyy-MM-dd
     * @return 当前日期格式字符串
     */
    private String getDateFormat(){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        return format.format(new Date());
    }
}
